#pragma once

#include <windows.h>
#include <vector>
#include <map>
#include <Base/CriticalRw.h>
#include <Base/CriticalSection.h>
#include <Base/Ref.h>
#include <Base/Traits.h>
#include <Base/InOut.h>
#include <Base/StringCtrl.h>
#include <Base/MemAllocate.h>
#include <Base/SmartX.h>
#include <OcfExt/OcfExt.h>
#include "memmngr.h"

using namespace __OCF_BASE__;

class CharInfo : public __OCF_BASE__::CRef<COcfAllocator>
{	
public:
	DWORD m_dwUserInfoID;
	BYTE m_byCharSlot;
	char m_szName[32];
	char m_nGender;
	DWORD m_dwCharExp;
	DWORD m_dwCharMoney;
	char m_isBlock;

	CharInfo()
	{
		m_dwUserInfoID = 0;
		m_byCharSlot = 0;
		ZeroMemory(m_szName, sizeof(m_szName));
		m_nGender = 0;
		m_dwCharExp = 0;
		m_dwCharMoney = 0;
		m_isBlock = 0;
	}

	void SetInfo(const DWORD dwUserInfoID, const BYTE bySlot, const char *szName, const ULONG ulNameLen, const char nGender, const DWORD dwCharExp, const DWORD dwCharMoney, const char isBlock)
	{
		m_dwUserInfoID = dwUserInfoID;
		m_byCharSlot = bySlot;
		__OCF_BASE__::StrCopy(m_szName, szName, ulNameLen);
		m_nGender = nGender;
		m_dwCharExp = dwCharExp;
		m_dwCharMoney = dwCharMoney;
		m_isBlock = isBlock;
	}
};

class UserInfo : public __OCF_BASE__::CRef<COcfAllocator>, public __OCF_BASE__::CCritical
{
public:
	DWORD m_dwUserSN;
	BYTE m_bySelectedChar;
	CharInfo *m_pCharInfo;

private:
	std::vector<CharInfo*, __OCF_BASE__::CStlAllocator<CharInfo *, COcfAllocator>> m_CharInfo;

public:
	typedef TYPE_LIST04(DWORD, BYTE, char, char*) _OUT_CHAR_INFO_T;
	typedef COut<_OUT_CHAR_INFO_T> _OUT_CHAR_T;
	typedef std::vector<CharInfo *, __OCF_BASE__::CStlAllocator<CharInfo *,COcfAllocator> >::iterator IterChar;

	UserInfo()
	{
		m_dwUserSN = 0;
		m_bySelectedChar = 100;

		m_pCharInfo = NULL;

		{
			SYNC_POINTER(this);
			for(int i = 0; i < 10; ++i)
				m_CharInfo.push_back(NULL);
		}
	}

	~UserInfo()
	{
		CharInfo *pCharInfo = NULL;
		IterChar chariter;

		{
			SYNC_POINTER(this);
			for(chariter = m_CharInfo.begin(); chariter != m_CharInfo.end(); ++chariter)
			{
				pCharInfo = *chariter;
				if(pCharInfo)
					pCharInfo->Release();
			}

			m_CharInfo.clear();

			m_pCharInfo->Release();
		}
	}

	BOOL FillUserInfoData(_OUT_CHAR_T &cOut)
	{
		LONG lPos = 0;
		BYTE byCount = 0;

		cOut.Push(byCount, &lPos);

		CharInfo *pCharInfo = NULL;
		IterChar chariter;

		byCount = 0;

		{
			SYNC_POINTER(this);
			for(chariter = m_CharInfo.begin(); chariter != m_CharInfo.end(); ++chariter)
			{
				pCharInfo = *chariter;
				if(pCharInfo)
				{
					++byCount;

					cOut.Push(pCharInfo->m_dwUserInfoID)
						.Push(pCharInfo->m_byCharSlot)
						.Push(StrLength(pCharInfo->m_szName, 32), pCharInfo->m_szName)
						.Push(pCharInfo->m_nGender)
						.Push(pCharInfo->m_dwCharExp)
						.Push(pCharInfo->m_dwCharMoney)
						.Push(pCharInfo->m_isBlock);
				}
			}
		}

		cOut.Replace(lPos, byCount);

		return cOut.IsValid();
	}

	bool isEmptyChar(){ SYNC_POINTER(this); return m_CharInfo.empty(); }

	void SetCharInfo(BYTE bySlot, CharInfo *pCharInfo)
	{
		SYNC_POINTER(this);

		if(NULL == pCharInfo && m_CharInfo[bySlot])
			m_CharInfo[bySlot]->Release();

		m_CharInfo[bySlot] = pCharInfo;

		if(pCharInfo)
			pCharInfo->AddRef();
	}

	CharInfo *GetCharInfo(BYTE bySlot)
	{ 
		SYNC_POINTER(this);
		CharInfo *pCharInfo = m_CharInfo[bySlot];
		
		if(pCharInfo)
			pCharInfo->AddRef();

		return pCharInfo;
	}

	void SetSelectCharInfo(BYTE bySlot, CharInfo *pCharInfo)
	{
		SYNC_POINTER(this);

		if(m_bySelectedChar < 10 && m_CharInfo[m_bySelectedChar])
		{
			m_CharInfo[m_bySelectedChar]->Release();
		}

		m_bySelectedChar = bySlot;
		m_pCharInfo = pCharInfo;

		if(pCharInfo)
			pCharInfo->AddRef();
	}

	CharInfo *GetSelectCharInfo()
	{
		SYNC_POINTER(this);
		if(m_bySelectedChar < 10 )
		{
			m_pCharInfo->AddRef();
			return m_pCharInfo;
		}

		return NULL;
	}
};

class UserInfoContainer : public __OCF_BASE__::CCritical
{
public:
	UserInfoContainer();
	~UserInfoContainer();

private:
	typedef std::pair<DWORD, UserInfo*> _USERINFO_PAIR_T;
	std::map<DWORD, UserInfo*, std::less<DWORD>, __OCF_BASE__::CStlAllocator<_USERINFO_PAIR_T,COcfAllocator>> m_MapUser;

	typedef std::map<DWORD, UserInfo*, std::less<DWORD>, __OCF_BASE__::CStlAllocator<_USERINFO_PAIR_T,COcfAllocator>>::iterator IterUser;

public:
	bool InsertUser(DWORD dwUserSN, UserInfo *pUserInfo);
	UserInfo *FindUser(DWORD dwUserSN);
	bool DeleteUser(DWORD dwUserSN);
};